home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / control.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  55KB  |  1,386 lines

  1. // $Id: control.cpp,v 1.28 1999/11/18 03:37:22 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <sys/stat.h>
  12. #include "control.h"
  13. #include "scanner.h"
  14. #include "parser.h"
  15. #include "semantic.h"
  16. #include "error.h"
  17. #include "bytecode.h"
  18. #include "case.h"
  19.  
  20.  
  21. Control::Control(ArgumentExpander &arguments, Option &option_) : return_code(0),
  22.                                                                  option(option_),
  23.                                                                  dot_classpath_index(0),
  24.                                                                  system_table(NULL),
  25.                                                                  system_semantic(NULL),
  26.                                                                  semantic(1024),
  27.                                                                  needs_body_work(1024),
  28.                                                                  type_trash_bin(1024),
  29.                                                                  input_java_file_set(1021),
  30.                                                                  input_class_file_set(1021),
  31.                                                                  expired_file_set(),
  32.                                                                  recompilation_file_set(1021),
  33.                                                                  int_pool(&bad_value),
  34.                                                                  long_pool(&bad_value),
  35.                                                                  float_pool(&bad_value),
  36.                                                                  double_pool(&bad_value),
  37.                                                                  Utf8_pool(&bad_value),
  38. #ifdef TEST
  39.                                                                  input_files_processed(0),
  40.                                                                  class_files_read(0),
  41.                                                                  class_files_written(0),
  42.                                                                  line_count(0),
  43. #endif
  44.                                                                  Serializable_type(NULL),
  45.                                                                  Object_type(NULL),
  46.                                                                  Cloneable_type(NULL),
  47.                                                                  String_type(NULL),
  48.                                                                  Void_type(NULL),
  49.                                                                  Boolean_type(NULL),
  50.                                                                  Byte_type(NULL),
  51.                                                                  Short_type(NULL),
  52.                                                                  Character_type(NULL),
  53.                                                                  Integer_type(NULL),
  54.                                                                  Long_type(NULL),
  55.                                                                  Float_type(NULL),
  56.                                                                  Double_type(NULL),
  57.                                                                  Class_type(NULL),
  58.                                                                  Throwable_type(NULL),
  59.                                                                  Exception_type(NULL),
  60.                                                                  RuntimeException_type(NULL),
  61.                                                                  ClassNotFoundException_type(NULL),
  62.                                                                  Error_type(NULL),
  63.                                                                  NoClassDefFoundError_type(NULL),
  64.                                                                  StringBuffer_type(NULL),
  65.  
  66.                                                                  Class_forName_method(NULL),
  67.  
  68.                                                                  Throwable_getMessage_method(NULL),
  69.  
  70.                                                                  NoClassDefFoundError_InitWithString_method(NULL),
  71.  
  72.                                                                  StringBuffer_Init_method(NULL),
  73.                                                                  StringBuffer_InitWithString_method(NULL),
  74.                                                                  StringBuffer_toString_method(NULL),
  75.                                                                  StringBuffer_append_char_array_method(NULL),
  76.                                                                  StringBuffer_append_char_method(NULL),
  77.                                                                  StringBuffer_append_boolean_method(NULL),
  78.                                                                  StringBuffer_append_int_method(NULL),
  79.                                                                  StringBuffer_append_long_method(NULL),
  80.                                                                  StringBuffer_append_float_method(NULL),
  81.                                                                  StringBuffer_append_double_method(NULL),
  82.                                                                  StringBuffer_append_string_method(NULL),
  83.                                                                  StringBuffer_append_object_method(NULL)
  84. {
  85.     ProcessGlobals();
  86.  
  87.     ProcessUnnamedPackage();
  88.  
  89.     ProcessPath();
  90.  
  91.     ProcessSystemInformation();
  92.  
  93.     //
  94.     // Instantiate a scanner and a parser and initialize the static members for the semantic processors.
  95.     //
  96.     scanner = new Scanner(*this);
  97.     parser = new Parser();
  98.     SemanticError::StaticInitializer();
  99.  
  100.     //
  101.     // Process all file names specified in command line
  102.     //
  103.     ProcessNewInputFiles(input_java_file_set, arguments, option.first_file_index);
  104.  
  105.     //
  106.     // For each input file, copy it into the input_files array and process its package declaration.
  107.     //
  108.     StoragePool *ast_pool = new StoragePool(64); // how much space do we need? estimate 64 tokens.
  109.     FileSymbol **input_files = new FileSymbol*[input_java_file_set.Size() + 1];
  110.     int num_files = 0;
  111.     for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  112.                      file_symbol;
  113.                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  114.     {
  115.         input_files[num_files++] = file_symbol;
  116.         scanner -> Scan(file_symbol);
  117.         if (file_symbol -> lex_stream) // did we have a successful scan!
  118.         {
  119.             AstPackageDeclaration *package_declaration = parser -> PackageHeaderParse(file_symbol -> lex_stream, ast_pool);
  120.             ProcessPackageDeclaration(file_symbol, package_declaration);
  121.             ast_pool -> Reset();
  122.         }
  123.     }
  124.  
  125.     //
  126.     //
  127.     //
  128.     FileSymbol *main_file_clone;
  129.     if (num_files > 0)
  130.         main_file_clone = input_files[0] -> Clone();
  131.     else
  132.     {
  133.         //
  134.         // Some name, any name !!! We use dot_name_symbol as a bad file name because
  135.         // no file can be named ".".
  136.         //
  137.         FileSymbol *file_symbol = classpath[dot_classpath_index] -> RootDirectory() -> InsertFileSymbol(dot_name_symbol);
  138.         file_symbol -> directory_symbol = classpath[dot_classpath_index] -> RootDirectory();
  139.         file_symbol -> SetJava();
  140.  
  141.         main_file_clone = file_symbol -> Clone();
  142.     }
  143.  
  144.     main_file_clone -> semantic = new Semantic(*this, main_file_clone);
  145.     system_semantic = main_file_clone -> semantic;
  146.     scanner -> SetUp(main_file_clone);
  147.  
  148. #ifdef WIN32_FILE_SYSTEM
  149.     //
  150.     //
  151.     //
  152.     if (option.BadMainDisk())
  153.     {
  154.         system_semantic -> ReportSemError(SemanticError::NO_CURRENT_DIRECTORY,
  155.                                           0,
  156.                                           0);
  157.     }
  158. #endif
  159.  
  160.     //
  161.     //
  162.     //
  163.     for (int o = 0; o < option.bad_options.Length(); o++)
  164.     {
  165.         system_semantic -> ReportSemError((SemanticError::SemanticErrorKind) option.bad_options[o] -> kind,
  166.                                           0,
  167.                                           0,
  168.                                           option.bad_options[o] -> name);
  169.     }
  170.  
  171.     if (java_util_package -> directory.Length() == 0)
  172.     {
  173.         system_semantic -> ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
  174.                                           0,
  175.                                           0,
  176.                                           StringConstant::US_java_SL_util);
  177.     }
  178.  
  179.     //
  180.     //
  181.     //
  182.     for (int l = 0; l < bad_zip_filenames.Length(); l++)
  183.     {
  184.         wchar_t *tail = &bad_zip_filenames[l][wcslen(bad_zip_filenames[l]) - 3];
  185.  
  186.         system_semantic -> ReportSemError(Case::StringSegmentEqual(tail, StringConstant::US__zip, 3) ||
  187.                                           Case::StringSegmentEqual(tail, StringConstant::US__jar, 3)
  188.                                                ? SemanticError::CANNOT_OPEN_ZIP_FILE
  189.                                                : SemanticError::CANNOT_OPEN_PATH_DIRECTORY,
  190.                                           0,
  191.                                           0,
  192.                                           bad_zip_filenames[l]);
  193.     }
  194.  
  195.     //
  196.     //
  197.     //
  198.     if (system_package -> directory.Length() == 0)
  199.     {
  200.         system_semantic -> ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
  201.                                           0,
  202.                                           0,
  203.                                           StringConstant::US_java_SL_lang);
  204.     }
  205.  
  206.     //
  207.     // When the -d option is specified, create the relevant
  208.     // directories if they don't already exist.
  209.     //
  210.     if (option.directory)
  211.     {
  212.         if (! ::SystemIsDirectory(option.directory))
  213.         {
  214.             for (char *ptr = option.directory; *ptr; ptr++)
  215.             {
  216.                 char delimiter = *ptr;
  217.                 if (delimiter == U_SLASH)
  218.                 {
  219.                     *ptr = U_NULL;
  220.  
  221.                     if (! ::SystemIsDirectory(option.directory))
  222.                         ::SystemMkdir(option.directory);
  223.  
  224.                     *ptr = delimiter;
  225.                 }
  226.             }
  227.  
  228.             ::SystemMkdir(option.directory);
  229.  
  230.             if (! ::SystemIsDirectory(option.directory))
  231.             {
  232.                 int length = strlen(option.directory);
  233.                 wchar_t *name = new wchar_t[length + 1];
  234.                 for (int i = 0; i < length; i++)
  235.                     name[i] = option.directory[i];
  236.                 name[length] = U_NULL;
  237.                 system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_DIRECTORY,
  238.                                                   0,
  239.                                                   0,
  240.                                                   name);
  241.                 delete [] name;
  242.             }
  243.         }
  244.     }
  245.  
  246.     //
  247.     //
  248.     //
  249.     for (int m = 0; m < bad_input_filenames.Length(); m++)
  250.     {
  251.         system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
  252.                                           0,
  253.                                           0,
  254.                                           bad_input_filenames[m]);
  255.     }
  256.  
  257.     //
  258.     //
  259.     //
  260.     for (int n = 0; n < unreadable_input_filenames.Length(); n++)
  261.     {
  262.         system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  263.                                           0,
  264.                                           0,
  265.                                           unreadable_input_filenames[n]);
  266.     }
  267.  
  268.     //
  269.     //
  270.     //
  271.     if (system_semantic -> NumErrors() > 0)
  272.     {
  273.         system_semantic -> PrintMessages();
  274.         return_code = system_semantic -> return_code;
  275.     }
  276.     else
  277.     {
  278.         system_semantic -> PrintMessages(); // there might be some warnings we want to print...
  279.  
  280.         //
  281.         //
  282.         //
  283.         input_java_file_set.SetEmpty();
  284.         for (int i = 0; i < num_files; i++)
  285.         {
  286.             FileSymbol *file_symbol = input_files[i];
  287.             if (! input_java_file_set.IsElement(file_symbol))
  288.                 ProcessFile(file_symbol);
  289.         }
  290.  
  291.         //
  292.         // Clean up all the files that have just been compiled in this new batch.
  293.         //
  294.         for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  295.                          file_symbol;
  296.                          file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  297.         {
  298.             CleanUp(file_symbol);
  299.         }
  300.  
  301.         //
  302.         // If more messages were added to system_semantic, print them...
  303.         //
  304.         system_semantic -> PrintMessages();
  305.         if (system_semantic -> return_code > 0 || bad_input_filenames.Length() > 0 || unreadable_input_filenames.Length() > 0)
  306.             return_code = 1;
  307.  
  308.         //
  309.         // If the incremental flag is on, check to see if the user wants us to recompile.
  310.         //
  311.         if (option.incremental)
  312.         {
  313.             option.depend = false; // The depend flag should only be in effect in the first pass
  314.  
  315.             for (bool recompile = IncrementalRecompilation(); recompile; recompile = IncrementalRecompilation())
  316.             {
  317.                 return_code = 0; // reset the return code as we may compile clean in this pass
  318.                 system_semantic -> return_code = 0;
  319.  
  320.                 //
  321.                 //
  322.                 //
  323.                 for (int m = 0; m < bad_input_filenames.Length(); m++)
  324.                 {
  325.                     system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
  326.                                                       0,
  327.                                                       0,
  328.                                                       bad_input_filenames[m]);
  329.                 }
  330.  
  331.                 //
  332.                 //
  333.                 //
  334.                 for (int n = 0; n < unreadable_input_filenames.Length(); n++)
  335.                 {
  336.                     system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  337.                                                       0,
  338.                                                       0,
  339.                                                       unreadable_input_filenames[n]);
  340.                 }
  341.  
  342.                 FileSymbol *file_symbol;
  343.  
  344.                 num_files = 0;
  345.                 delete [] input_files; // delete previous copy
  346.                 input_files = new FileSymbol*[recompilation_file_set.Size()];
  347.                 for (file_symbol = (FileSymbol *) recompilation_file_set.FirstElement();
  348.                      file_symbol;
  349.                      file_symbol = (FileSymbol *) recompilation_file_set.NextElement())
  350.                 {
  351.                     input_java_file_set.RemoveElement(file_symbol);
  352.                     input_files[num_files++] = file_symbol;
  353.  
  354.                     LexStream *lex_stream = file_symbol -> lex_stream;
  355.                     if (lex_stream)
  356.                     {
  357.                         AstPackageDeclaration *package_declaration = parser -> PackageHeaderParse(lex_stream, ast_pool);
  358.                         ProcessPackageDeclaration(file_symbol, package_declaration);
  359.                         ast_pool -> Reset();
  360.                     }
  361.                 }
  362.  
  363.                 //
  364.                 // If a file has been erased, remove it from the input file set.
  365.                 //
  366.                 for (file_symbol = (FileSymbol *) expired_file_set.FirstElement();
  367.                      file_symbol;
  368.                      file_symbol = (FileSymbol *) expired_file_set.NextElement())
  369.                 {
  370.                     input_java_file_set.RemoveElement(file_symbol);
  371.                 }
  372.  
  373.                 //
  374.                 // Reset the global objects before recompiling this new batch.
  375.                 //
  376.                 expired_file_set.SetEmpty();
  377.                 recompilation_file_set.SetEmpty();
  378.                 type_trash_bin.Reset();
  379.  
  380.                 //
  381.                 // For each file that should be recompiled, process it if it has not
  382.                 // already been dragged in by dependence.
  383.                 //
  384.                 for (int k = 0; k < num_files; k++)
  385.                 {
  386.                     FileSymbol *file_symbol = input_files[k];
  387.                     if (! input_java_file_set.IsElement(file_symbol))
  388.                         ProcessFile(file_symbol);
  389.                 }
  390.  
  391.                 //
  392.                 // Clean up all the files that have just been compiled in this new batch.
  393.                 //
  394.                 for (file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  395.                     // delete file_symbol
  396.                      file_symbol;
  397.                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  398.                 {
  399.                     // delete file_symbol
  400.                     CleanUp(file_symbol);
  401.                 }
  402.  
  403.                 //
  404.                 // If any system error or warning was detected, print it...
  405.                 //
  406.                 system_semantic -> PrintMessages();
  407.                 if (system_semantic -> return_code > 0 || bad_input_filenames.Length() > 0 || unreadable_input_filenames.Length() > 0)
  408.                     return_code = 1;
  409.             }
  410.         }
  411.  
  412.         //
  413.         // Are we supposed to generate Makefiles?
  414.         //
  415.         if (option.makefile)
  416.         {
  417.             if (option.dependence_report)
  418.             {
  419.                 FILE *outfile = ::SystemFopen(option.dependence_report_name, "w");
  420.                 if (outfile == NULL)
  421.                     Coutput << "*** Cannot open file " << option.dependence_report_name << "\n";
  422.                 else
  423.                 {
  424.                     SymbolSet types_in_new_files;
  425.  
  426.                     for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  427.                                      file_symbol;
  428.                                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  429.                     {
  430.                         char *java_name = file_symbol -> FileName();
  431.  
  432.                         for (int j = 0; j < file_symbol -> types.Length(); j++)
  433.                         {
  434.                             TypeSymbol *type = file_symbol -> types[j];
  435. #ifdef EBCDIC
  436.                             for (char *p = java_name; *p; p++)
  437.                                  fprintf(outfile, "%c", Code::ToEBCDIC(*p));
  438.                             fprintf(outfile, " : ");
  439.                             for (char *q = type -> SignatureString(); *q; q++)
  440.                                  fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  441.                             fprintf(outfile, "\n");
  442. #else
  443.                             fprintf(outfile, "%s : %s\n", java_name, type -> SignatureString());
  444. #endif
  445.  
  446.                             //
  447.                             //
  448.                             //
  449.                             for (TypeSymbol *static_parent = (TypeSymbol *) type -> static_parents -> FirstElement();
  450.                                              static_parent;
  451.                                              static_parent = (TypeSymbol *) type -> static_parents -> NextElement())
  452.                             {
  453.                                 if (! type -> parents -> IsElement(static_parent)) // Only a static reference to static_parent?
  454.                                 {
  455. #ifdef EBCDIC
  456.                                     fprintf(outfile, "   !");
  457.                                     for (char *q = static_parent -> SignatureString(); *q; q++)
  458.                                          fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  459.                                     fprintf(outfile, "\n");
  460. #else
  461.                                     fprintf(outfile, "   !%s\n", static_parent -> SignatureString());
  462. #endif
  463.  
  464.                                     //
  465.                                     // If the type is contained in a type that is not one of the input files, save it
  466.                                     //
  467.                                     if (static_parent -> file_symbol -> IsClass())
  468.                                         types_in_new_files.AddElement(static_parent);
  469.                                 }
  470.                             }
  471.  
  472.                             //
  473.                             //
  474.                             //
  475.                             for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
  476.                                              parent;
  477.                                              parent = (TypeSymbol *) type -> parents -> NextElement())
  478.                             {
  479. #ifdef EBCDIC
  480.                                 fprintf(outfile, "    ");
  481.                                 for (char *q = parent -> SignatureString(); *q; q++)
  482.                                      fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  483.                                 fprintf(outfile, "\n");
  484. #else
  485.                                 fprintf(outfile, "    %s\n", parent -> SignatureString());
  486. #endif
  487.  
  488.                                 //
  489.                                 // If the type is contained in a type that is not one of the input files, save it
  490.                                 //
  491.                                 if (parent -> file_symbol -> IsClass())
  492.                                     types_in_new_files.AddElement(parent);
  493.                             }
  494.                         }
  495.                     }
  496.  
  497.                     //
  498.                     // Print the list of class files that are referenced.
  499.                     //
  500.                     for (TypeSymbol *type = (TypeSymbol *) types_in_new_files.FirstElement();
  501.                                      type;
  502.                                      type = (TypeSymbol *) types_in_new_files.NextElement())
  503.                     {
  504.                         char *class_name = type -> file_symbol -> FileName();
  505. #ifdef EBCDIC
  506.                         for (char *p = class_name; *p; p++)
  507.                              fprintf(outfile, "%c", Code::ToEBCDIC(*p));
  508.                         fprintf(outfile, " : ");
  509.                         for (char *q = type -> SignatureString(); *q; q++)
  510.                              fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  511.                         fprintf(outfile, "\n");
  512. #else
  513.                         fprintf(outfile, "%s : %s\n", class_name, type -> SignatureString());
  514. #endif
  515.                     }
  516.  
  517.                     fclose(outfile);
  518.                 }
  519.             }
  520.             else
  521.             {
  522.                 SymbolSet *candidates = new SymbolSet(input_java_file_set.Size() + input_class_file_set.Size());
  523.                 *candidates = input_java_file_set;
  524.                 candidates -> Union(input_class_file_set);
  525.  
  526.                 TypeDependenceChecker *dependence_checker = new TypeDependenceChecker((Control *) this, *candidates, type_trash_bin);
  527.                 dependence_checker -> PartialOrder();
  528.                 dependence_checker -> OutputDependences();
  529.                 delete dependence_checker;
  530.  
  531.                 delete candidates;
  532.             }
  533.         }
  534.     }
  535.  
  536.     delete ast_pool;
  537.  
  538.     delete main_file_clone; // delete the clone of the main source file...
  539.  
  540. #ifdef NO_LEAKS
  541.     delete [] input_files;
  542. #endif
  543.  
  544.     return;
  545. }
  546.  
  547.  
  548. Control::~Control()
  549. {
  550. #ifdef NO_LEAKS
  551.     for (int i = 0; i < bad_zip_filenames.Length(); i++)
  552.         delete [] bad_zip_filenames[i];
  553.  
  554.     for (int j = 0; j < bad_input_filenames.Length(); j++)
  555.         delete [] bad_input_filenames[j];
  556.  
  557.     for (int k = 0; k < unreadable_input_filenames.Length(); k++)
  558.         delete [] unreadable_input_filenames[k];
  559.  
  560.     for (int l = 0; l < system_directories.Length(); l++)
  561.         delete system_directories[l];
  562.  
  563.     delete scanner;
  564.     delete parser;
  565.     delete system_semantic;
  566. #endif
  567.  
  568. #ifdef TEST
  569.     if (option.debug_dump_lex || option.debug_dump_ast || option.debug_unparse_ast)
  570.     {
  571.         Coutput << line_count << " source lines read\n\n"
  572.                 << class_files_read << " \".class\" files read\n"
  573.                 << class_files_written << " \".class\" files written\n"
  574.                 << input_files_processed << " \".java\" files processed\n";
  575.     }
  576. #endif
  577. }
  578.  
  579.  
  580. PackageSymbol *Control::ProcessPackage(wchar_t *name)
  581. {
  582.     int name_length = wcslen(name);
  583.     wchar_t *package_name = new wchar_t[name_length];
  584.     int length;
  585.     for (length = 0; length < name_length && name[length] != U_SLASH; length++)
  586.          package_name[length] = name[length];
  587.     NameSymbol *name_symbol = FindOrInsertName(package_name, length);
  588.  
  589.     PackageSymbol *package_symbol = external_table.FindPackageSymbol(name_symbol);
  590.     if (! package_symbol)
  591.     {
  592.         package_symbol = external_table.InsertPackageSymbol(name_symbol, NULL);
  593.         FindPathsToDirectory(package_symbol);
  594.     }
  595.  
  596.     while(length < name_length)
  597.     {
  598.         int start = ++length;
  599.         for (int i = 0; length < name_length && name[length] != U_SLASH; i++, length++)
  600.              package_name[i] = name[length];
  601.         name_symbol = FindOrInsertName(package_name, length - start);
  602.         PackageSymbol *subpackage_symbol = package_symbol -> FindPackageSymbol(name_symbol);
  603.         if (! subpackage_symbol)
  604.         {
  605.             subpackage_symbol = package_symbol -> InsertPackageSymbol(name_symbol);
  606.             FindPathsToDirectory(subpackage_symbol);
  607.         }
  608.         package_symbol = subpackage_symbol;
  609.     }
  610.  
  611.     delete [] package_name;
  612.  
  613.     return package_symbol;
  614. }
  615.  
  616.  
  617. //
  618. // When searching for a subdirectory in a zipped file, it must already be present in the
  619. // hierarchy.
  620. //
  621. DirectorySymbol *Control::FindSubdirectory(PathSymbol *path_symbol, wchar_t *name, int name_length)
  622. {
  623.     wchar_t *directory_name = new wchar_t[name_length + 1];
  624.  
  625.     DirectorySymbol *directory_symbol = path_symbol -> RootDirectory();
  626.     for (int start = 0, end; directory_symbol && start < name_length; start = end + 1)
  627.     {
  628.         end = start;
  629.         for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  630.              directory_name[i] = name[end];
  631.         NameSymbol *name_symbol = FindOrInsertName(directory_name, end - start);
  632.         directory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  633.     }
  634.  
  635.     delete [] directory_name;
  636.  
  637.     return directory_symbol;
  638. }
  639.  
  640.  
  641. //
  642. // When searching for a directory in the system, if it is not already present in the hierarchy
  643. // insert it and attempt to read it from the system...
  644. //
  645. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  646.     DirectorySymbol *Control::ProcessSubdirectories(wchar_t *source_name, int source_name_length)
  647.     {
  648.         int name_length = (source_name_length < 0 ? 0 : source_name_length);
  649.         char *input_name = new char[name_length + 1];
  650.         for (int i = 0; i < name_length; i++)
  651.             input_name[i] = source_name[i];
  652.         input_name[name_length] = U_NULL;
  653.  
  654.         DirectorySymbol *directory_symbol = NULL;
  655.         struct stat status;
  656.         if ((::SystemStat(input_name, &status) == 0) && (status.st_mode & STAT_S_IFDIR))
  657.             directory_symbol = system_table -> FindDirectorySymbol(status.st_dev, status.st_ino);
  658.  
  659.         if (! directory_symbol)
  660.         {
  661.             if (input_name[0] == U_SLASH) // file name starts with '/'
  662.             {
  663.                 directory_symbol = new DirectorySymbol(FindOrInsertName(source_name, name_length), classpath[dot_classpath_index]);
  664.                 directory_symbol -> ReadDirectory();
  665.                 system_directories.Next() = directory_symbol;
  666.                 system_table -> InsertDirectorySymbol(status.st_dev, status.st_ino, directory_symbol);
  667.             }
  668.             else
  669.             {
  670.                 wchar_t *name = new wchar_t[name_length + 1];
  671.                 for (int i = 0; i < name_length; i++)
  672.                     name[i] = source_name[i];
  673.                 name[name_length] = U_NULL;
  674.  
  675.                 directory_symbol = classpath[dot_classpath_index] -> RootDirectory(); // start at the dot directory.
  676.  
  677.                 //
  678.                 //
  679.                 //
  680.                 wchar_t *directory_name = new wchar_t[name_length];
  681.                 int end = 0;
  682.                 for (int start = end; start < name_length; start = end)
  683.                 {
  684.                     int length;
  685.                     for (length = 0; end < name_length && name[end] != U_SLASH; length++, end++)
  686.                         directory_name[length] = name[end];
  687.  
  688.                     if (length != 1 || directory_name[0] != U_DOT) // Not the current directory
  689.                     {
  690.                         if (length == 2 && directory_name[0] == U_DOT && directory_name[1] == U_DOT) // keep the current directory
  691.                         {
  692.                             if (directory_symbol -> Identity() == dot_name_symbol ||
  693.                                 directory_symbol -> Identity() == dot_dot_name_symbol)
  694.                             {
  695.                                 DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  696.                                 if (! subdirectory_symbol)
  697.                                     subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol);
  698.                                 directory_symbol = subdirectory_symbol;
  699.                             }
  700.                             else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  701.                         }
  702.                         else
  703.                         {
  704.                             NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  705.                             DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  706.                             if (! subdirectory_symbol)
  707.                                 subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  708.                             directory_symbol = subdirectory_symbol;
  709.                         }
  710.                     }
  711.  
  712.                     for (end++; end < name_length && name[end] == U_SLASH; end++) // skip all extra '/'
  713.                         ;
  714.                 }
  715.  
  716.                 //
  717.                 // Insert the new directory into the system table to avoid duplicates, in case
  718.                 // the same directory is specified with a different name.
  719.                 //
  720.                 if (directory_symbol != classpath[dot_classpath_index] -> RootDirectory()) // Not the dot directory.
  721.                 {
  722.                     system_table -> InsertDirectorySymbol(status.st_dev, status.st_ino, directory_symbol);
  723.                     directory_symbol -> ReadDirectory();
  724.                 }
  725.  
  726.                 delete [] directory_name;
  727.                 delete [] name;
  728.             }
  729.         }
  730.  
  731.         delete [] input_name;
  732.  
  733.         return directory_symbol;
  734.     }
  735. #elif defined(WIN32_FILE_SYSTEM)
  736.     DirectorySymbol *Control::ProcessSubdirectories(wchar_t *source_name, int source_name_length)
  737.     {
  738.         DirectorySymbol *directory_symbol = classpath[dot_classpath_index] -> RootDirectory();
  739.  
  740.         int name_length = (source_name_length < 0 ? 0 : source_name_length);
  741.         wchar_t *name = new wchar_t[name_length + 1];
  742.         char *input_name = new char[name_length + 1];
  743.         for (int i = 0; i < name_length; i++)
  744.             input_name[i] = name[i] = source_name[i];
  745.         input_name[name_length] = name[name_length] = U_NULL;
  746.  
  747.         if (name_length >= 2 && Case::IsAsciiAlpha(input_name[0]) && input_name[1] == U_COLON) // a disk was specified
  748.         {
  749.             char disk = input_name[0];
  750.             option.SaveCurrentDirectoryOnDisk(disk);
  751.             if (SetCurrentDirectory(input_name))
  752.             {
  753.                 DWORD directory_length = GetCurrentDirectory(0, input_name); // first, get the right size
  754.                 char *full_directory_name = new char[directory_length + 1];  // allocate the directory
  755.                 DWORD length = GetCurrentDirectory(directory_length, full_directory_name);
  756.                 if (length <= directory_length)
  757.                 {
  758.                     for (char *ptr = full_directory_name; *ptr; ptr++)
  759.                         *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  760.  
  761.                     char *current_directory = option.GetMainCurrentDirectory();
  762.                     int prefix_length = strlen(current_directory);
  763.                     int start = (prefix_length <= length &&
  764.                                  Case::StringSegmentEqual(current_directory, full_directory_name, prefix_length) &&
  765.                                  (full_directory_name[prefix_length] == U_SLASH || full_directory_name[prefix_length] == U_NULL)
  766.                                                 ? prefix_length + 1
  767.                                                 : 0);
  768.  
  769.                     if (start > length)
  770.                          name_length = 0;
  771.                     else if (start <= length) // note that we can assert that (start != length)
  772.                     {
  773.                         delete [] name;
  774.                         name_length = length - start;
  775.                         name = new wchar_t[name_length + 1];
  776.                         for (int k = 0, i = start; i < length; i++, k++)
  777.                             name[k] = full_directory_name[i];
  778.                         name[name_length] = U_NULL;
  779.                     }
  780.                 }
  781.  
  782.                 delete [] full_directory_name;
  783.             }
  784.  
  785.             option.ResetCurrentDirectoryOnDisk(disk);  // reset the current directory on this disk
  786.             option.SetMainCurrentDirectory(); // reset the real current directory...
  787.         }
  788.  
  789.         //
  790.         //
  791.         //
  792.         int end;
  793.         if (name_length > 2 && Case::IsAsciiAlpha(name[0]) && name[1] == U_COLON && name[2] == U_SLASH)
  794.             end = 3;
  795.         else
  796.         {
  797.             for (end = 0; end < name_length && name[end] == U_SLASH; end++) // keep all extra leading '/'
  798.                 ;
  799.         }
  800.  
  801.         //
  802.         //
  803.         //
  804.         wchar_t *directory_name = new wchar_t[name_length];
  805.         int length;
  806.         if (end > 0)
  807.         {
  808.             for (length = 0; length < end; length++)
  809.                 directory_name[length] = name[length];
  810.             NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  811.             DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  812.             if (! subdirectory_symbol)
  813.                 subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  814.             directory_symbol = subdirectory_symbol;
  815.         }
  816.  
  817.         //
  818.         //
  819.         //
  820.         for (int start = end; start < name_length; start = end)
  821.         {
  822.             for (length = 0; end < name_length && name[end] != U_SLASH; length++, end++)
  823.                 directory_name[length] = name[end];
  824.  
  825.             if (length != 1 || directory_name[0] != U_DOT) // Not the current directory
  826.             {
  827.                 if (length == 2 && directory_name[0] == U_DOT && directory_name[1] == U_DOT) // keep the current directory
  828.                 {
  829.                     if (directory_symbol -> Identity() == dot_name_symbol || directory_symbol -> Identity() == dot_dot_name_symbol)
  830.                     {
  831.                         DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  832.                         if (! subdirectory_symbol)
  833.                             subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol);
  834.                         directory_symbol = subdirectory_symbol;
  835.                     }
  836.                     else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  837.                 }
  838.                 else
  839.                 {
  840.                     NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  841.                     DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  842.                     if (! subdirectory_symbol)
  843.                         subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  844.                     directory_symbol = subdirectory_symbol;
  845.                 }
  846.             }
  847.  
  848.             for (end++; end < name_length && name[end] == U_SLASH; end++) // skip all extra '/'
  849.                 ;
  850.         }
  851.  
  852.         directory_symbol -> ReadDirectory();
  853.  
  854.         delete [] directory_name;
  855.         delete [] name;
  856.         delete [] input_name;
  857.  
  858.         return directory_symbol;
  859.     }
  860. #endif
  861.  
  862.  
  863. void Control::ProcessNewInputFiles(SymbolSet &file_set, ArgumentExpander &arguments, int first_index)
  864. {
  865.     for (int i = 0; i < bad_input_filenames.Length(); i++)
  866.         delete [] bad_input_filenames[i];
  867.     bad_input_filenames.Reset();
  868.  
  869.     for (int k = 0; k < unreadable_input_filenames.Length(); k++)
  870.         delete [] unreadable_input_filenames[k];
  871.     unreadable_input_filenames.Reset();
  872.  
  873.     //
  874.     // Process all file names specified in command line
  875.     //
  876.     for (int j = first_index; j < arguments.argc; j++)
  877.     {
  878.         char *file_name = arguments.argv[j];
  879.         int file_name_length = strlen(file_name);
  880.  
  881.         wchar_t *name = new wchar_t[file_name_length + 1];
  882.         for (int i = 0; i < file_name_length; i++)
  883.             name[i] = (file_name[i] != U_BACKSLASH ? file_name[i] : (wchar_t) U_SLASH); // change backslash to forward slash.
  884.         name[file_name_length] = U_NULL;
  885.  
  886.         //
  887.         // File must be of the form xxx.java where xxx is a
  888.         // character string consisting of at least one character.
  889.         //
  890.         if (file_name_length < FileSymbol::java_suffix_length ||
  891.             (! FileSymbol::IsJavaSuffix(&file_name[file_name_length - FileSymbol::java_suffix_length])))
  892.             bad_input_filenames.Next() = name;
  893.         else
  894.         {
  895.             FileSymbol *file_symbol = FindOrInsertJavaInputFile(name, file_name_length - FileSymbol::java_suffix_length);
  896.  
  897.             if (! file_symbol)
  898.                 unreadable_input_filenames.Next() = name;
  899.             else
  900.             {
  901.                 delete [] name;
  902.                 file_set.AddElement(file_symbol);
  903.             }
  904.         }
  905.     }
  906.  
  907.     return;
  908. }
  909.  
  910.  
  911. FileSymbol *Control::FindOrInsertJavaInputFile(DirectorySymbol *directory_symbol, NameSymbol *file_name_symbol)
  912. {
  913.     FileSymbol *file_symbol = NULL;
  914.  
  915.     int length = file_name_symbol -> Utf8NameLength() + FileSymbol::java_suffix_length;
  916.     char *java_name = new char[length + 1]; // +1 for \0
  917.     strcpy(java_name, file_name_symbol -> Utf8Name());
  918.     strcat(java_name, FileSymbol::java_suffix);
  919.  
  920.     DirectoryEntry *entry = directory_symbol -> FindEntry(java_name, length);
  921.     if (entry)
  922.     {
  923.         file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
  924.  
  925.         if (! file_symbol)
  926.         {
  927.             file_symbol = directory_symbol -> InsertFileSymbol(file_name_symbol);
  928.             file_symbol -> directory_symbol = directory_symbol;
  929.             file_symbol -> SetJava();
  930.         }
  931.  
  932.         file_symbol -> mtime = entry -> Mtime();
  933.     }
  934.  
  935.     delete [] java_name;
  936.  
  937.     return file_symbol;
  938. }
  939.  
  940.  
  941. FileSymbol *Control::FindOrInsertJavaInputFile(wchar_t *name, int name_length)
  942. {
  943.     FileSymbol *file_symbol = NULL;
  944.  
  945.     //
  946.     // The name has been preprocessed so that if it contains any
  947.     // slashes it is a forward slash. In the loop below we look
  948.     // for the occurrence of the first slash (if any) that separates
  949.     // the file name from its directory name.
  950.     //
  951.     DirectorySymbol *directory_symbol;
  952.     NameSymbol *file_name_symbol;
  953. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  954.     int len;
  955.     for (len = name_length - 1; len >= 0 && name[len] != U_SLASH; len--)
  956.         ;
  957.     directory_symbol = ProcessSubdirectories(name, len);
  958.     file_name_symbol = FindOrInsertName(&name[len + 1], name_length - (len + 1));
  959. #elif defined(WIN32_FILE_SYSTEM)
  960.     int len;
  961.     for (len = name_length - 1; len >= 0 && name[len] != U_SLASH && name[len] != U_COLON; len--)
  962.         ;
  963.     directory_symbol = ProcessSubdirectories(name, (name[len] == U_COLON ? len + 1 : len));
  964.     file_name_symbol = FindOrInsertName(&name[len + 1], name_length - (len + 1));
  965. #endif
  966.  
  967.     for (int i = 1; i < classpath.Length(); i++)
  968.     {
  969.         if (i == dot_classpath_index) // the current directory (.).
  970.         {
  971.             file_symbol = FindOrInsertJavaInputFile(directory_symbol, file_name_symbol);
  972.             if (file_symbol)
  973.                 break;
  974.         }
  975.         else if (classpath[i] -> IsZip())
  976.         {
  977.             DirectorySymbol *directory_symbol = FindSubdirectory(classpath[i], name, len);
  978.             if (directory_symbol)
  979.             {
  980.                 file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
  981.                 if (file_symbol && file_symbol -> IsJava())
  982.                      break;
  983.                 else file_symbol = NULL;
  984.             }
  985.         }
  986.     }
  987.  
  988.     //
  989.     // If the file was found, return it; otherwise, in case the (.) directory was not specified in the
  990.     // classpath, search for the file in it...
  991.     //
  992.     return (file_symbol ? file_symbol : FindOrInsertJavaInputFile(directory_symbol, file_name_symbol));
  993. }
  994.  
  995.  
  996. PackageSymbol *Control::FindOrInsertPackage(LexStream *lex_stream, AstExpression *name)
  997. {
  998.     PackageSymbol *package;
  999.  
  1000.     AstFieldAccess* field_access = name -> FieldAccessCast();
  1001.     if (field_access)
  1002.     {
  1003.         package = FindOrInsertPackage(lex_stream, field_access -> base);
  1004.         NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
  1005.         PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
  1006.         if (! subpackage)
  1007.             subpackage = package -> InsertPackageSymbol(name_symbol);
  1008.         package = subpackage;
  1009.     }
  1010.     else
  1011.     {
  1012.         AstSimpleName *simple_name = (AstSimpleName *) name;
  1013.         NameSymbol *name_symbol = lex_stream -> NameSymbol(simple_name -> identifier_token);
  1014.         package = external_table.FindPackageSymbol(name_symbol);
  1015.         if (! package)
  1016.             package = external_table.InsertPackageSymbol(name_symbol, NULL);
  1017.     }
  1018.  
  1019.     FindPathsToDirectory(package);
  1020.  
  1021.     return package;
  1022. }
  1023.  
  1024.  
  1025. void Control::ProcessFile(FileSymbol *file_symbol)
  1026. {
  1027.     ProcessHeaders(file_symbol);
  1028.  
  1029.     //
  1030.     // As long as there are new bodies, ...
  1031.     //
  1032.     for (int i = 0; i < needs_body_work.Length(); i++)
  1033.     {
  1034.         assert(semantic.Length() == 0);
  1035.  
  1036.         ProcessBodies(needs_body_work[i]);
  1037.     }
  1038.     needs_body_work.Reset();
  1039.  
  1040.     return;
  1041. }
  1042.  
  1043.  
  1044. void Control::ProcessHeaders(FileSymbol *file_symbol)
  1045. {
  1046.     input_java_file_set.AddElement(file_symbol);
  1047.  
  1048.     bool initial_invocation = (semantic.Length() == 0);
  1049.  
  1050.     if (option.verbose)
  1051.     {
  1052.         Coutput << "[read "
  1053.                 << file_symbol -> FileName()
  1054.                 << "]\n";
  1055.     }
  1056.  
  1057.     if (! file_symbol -> lex_stream)
  1058.          scanner -> Scan(file_symbol);
  1059.     else file_symbol -> lex_stream -> Reset();
  1060.  
  1061.     if (file_symbol -> lex_stream) // do we have a successful scan!
  1062.     {
  1063.         if (! file_symbol -> compilation_unit)
  1064.             file_symbol -> compilation_unit = parser -> HeaderParse(file_symbol -> lex_stream);
  1065.         //
  1066.         // If we have a compilation unit, analyze it, process its types.
  1067.         //
  1068.         if (file_symbol -> compilation_unit)
  1069.         {
  1070.             assert(! file_symbol -> semantic);
  1071.  
  1072.             if (! file_symbol -> package)
  1073.                 ProcessPackageDeclaration(file_symbol, file_symbol -> compilation_unit -> package_declaration_opt);
  1074.             file_symbol -> semantic = new Semantic(*this, file_symbol);
  1075.             semantic.Next() = file_symbol -> semantic;
  1076.             file_symbol -> semantic -> ProcessTypeNames();
  1077.         }
  1078.     }
  1079.  
  1080.     if (initial_invocation)
  1081.         ProcessMembers();
  1082.  
  1083.     return;
  1084. }
  1085.  
  1086.  
  1087. void Control::ProcessMembers()
  1088. {
  1089.     Tuple<TypeSymbol *> partially_ordered_types(1024);
  1090.     SymbolSet needs_member_work(101);
  1091.     TypeCycleChecker cycle_checker(partially_ordered_types);
  1092.     TopologicalSort topological_sorter(needs_member_work, partially_ordered_types);
  1093.  
  1094.     int start = 0;
  1095.     while (start < semantic.Length())
  1096.     {
  1097.         needs_member_work.SetEmpty();
  1098.  
  1099.         do
  1100.         {
  1101.             //
  1102.             // Check whether or not there are cycles in this new batch of types.
  1103.             // Create a partial order of the types (cycles are ordered arbitrarily)
  1104.             // and place the result in partially_ordered_types.
  1105.             //
  1106.             cycle_checker.PartialOrder(semantic, start);
  1107.             start = semantic.Length(); // next starting point
  1108.  
  1109.             //
  1110.             // Process the extends and implements clauses.
  1111.             //
  1112.             for (int j = 0; j < partially_ordered_types.Length(); j++)
  1113.             {
  1114.                 TypeSymbol *type = partially_ordered_types[j];
  1115.                 needs_member_work.AddElement(type);
  1116.                 type -> ProcessTypeHeaders();
  1117.                 type -> semantic_environment -> sem -> types_to_be_processed.AddElement(type);
  1118.             }
  1119.         } while (start < semantic.Length());
  1120.  
  1121.         //
  1122.         // Patially order the collection of types in needs_member_work and place the result
  1123.         // in partially_ordered_types. This reordering is based on the complete "supertype"
  1124.         // information computed in ProcessTypeHeaders.
  1125.         //
  1126.         topological_sorter.Sort();
  1127.         for (int i = 0; i < partially_ordered_types.Length(); i++)
  1128.         {
  1129.             TypeSymbol *type = partially_ordered_types[i];
  1130.             needs_body_work.Next() = type;
  1131.             type -> ProcessMembers();
  1132.         }
  1133.     }
  1134.  
  1135.     semantic.Reset();
  1136.  
  1137.     return;
  1138. }
  1139.  
  1140.  
  1141.  
  1142. void Control::ProcessBodies(TypeSymbol *type)
  1143. {
  1144.     Semantic *sem = type -> semantic_environment -> sem;
  1145.  
  1146.     if (type -> declaration && (! sem -> compilation_unit -> BadCompilationUnitCast()))
  1147.     {
  1148.         AstInterfaceDeclaration *interface_declaration = type -> declaration -> InterfaceDeclarationCast();
  1149.         AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
  1150.  
  1151. #ifdef WIN32_FILE_SYSTEM
  1152.         if (! type -> file_symbol -> IsZip())
  1153.         {
  1154.             int length = type -> Utf8NameLength() + FileSymbol::class_suffix_length;
  1155.             char *classfile_name = new char[length + 1]; // +1 for "\0"
  1156.             strcpy(classfile_name, type -> Utf8Name());
  1157.             strcat(classfile_name, FileSymbol::class_suffix);
  1158.  
  1159.             DirectorySymbol *directory = type -> file_symbol -> OutputDirectory();
  1160.             DirectoryEntry *entry = directory -> FindCaseInsensitiveEntry(classfile_name, length);
  1161.  
  1162.             //
  1163.             // If no entry exists for the classfile name, add it as we are about to create
  1164.             // such a file. If an entry is found and it is not identical (in a case-sensitive test)
  1165.             // to the name of the type, issue an appropriate message.
  1166.             //
  1167.             if (! entry)
  1168.                 directory -> InsertEntry(classfile_name, length);
  1169.             else if (strcmp(classfile_name, entry -> name) != 0)
  1170.             {
  1171.                 wchar_t *entry_name = new wchar_t[entry -> length + 1];
  1172.                 for (int i = 0; i < length; i++)
  1173.                     entry_name[i] = entry -> name[i];
  1174.                 entry_name[entry -> length] = U_NULL;
  1175.                 LexStream::TokenIndex identifier_token = (interface_declaration ? interface_declaration -> identifier_token
  1176.                                                                                 : class_declaration -> identifier_token);
  1177.  
  1178.                 sem -> ReportSemError(SemanticError::FILE_FILE_CONFLICT,
  1179.                                       identifier_token,
  1180.                                       identifier_token,
  1181.                                       type -> Name(),
  1182.                                       entry_name,
  1183.                                       directory -> Name());
  1184.  
  1185.                 delete [] entry_name;
  1186.             }
  1187.  
  1188.             delete [] classfile_name;
  1189.         }
  1190. #endif
  1191.  
  1192.         if (interface_declaration)
  1193.         {
  1194.             if (! parser -> InitializerParse(sem -> lex_stream, interface_declaration))
  1195.                 sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // recall that syntax errors were detected
  1196.             else
  1197.             {
  1198.                 type -> CompleteSymbolTable();
  1199.                 if (! parser -> BodyParse(sem -> lex_stream, interface_declaration))
  1200.                      sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // mark that syntax errors were detected
  1201.                 else type -> ProcessExecutableBodies();
  1202.             }
  1203.         }
  1204.         else
  1205.         {
  1206.             if (! parser -> InitializerParse(sem -> lex_stream, class_declaration -> class_body))
  1207.                 sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // recall that syntax errors were detected
  1208.             else
  1209.             {
  1210.                 type -> CompleteSymbolTable();
  1211.                 if (! parser -> BodyParse(sem -> lex_stream, class_declaration -> class_body))
  1212.                      sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // mark that syntax errors were detected.
  1213.                 else type -> ProcessExecutableBodies();
  1214.             }
  1215.         }
  1216.  
  1217.         if ((sem -> NumErrors() == 0) && (! sem -> compilation_unit -> BadCompilationUnitCast()))
  1218.         {
  1219.             Tuple<TypeSymbol *> *types = new Tuple<TypeSymbol *>(1024);
  1220.             types -> Next() = type;
  1221.  
  1222.             for (int j = 0; j < type -> num_anonymous_types(); j++)
  1223.             {
  1224.                 types -> Next() = type -> AnonymousType(j);
  1225.             }
  1226.  
  1227.             if (type -> local)
  1228.             {
  1229.                 for (TypeSymbol *local_type = (TypeSymbol *) type -> local -> FirstElement();
  1230.                                  local_type;
  1231.                                  local_type = (TypeSymbol *) type -> local -> NextElement())
  1232.                 {
  1233.                     types -> Next() = local_type;
  1234.                 }
  1235.             }
  1236.  
  1237.             if (type -> non_local)
  1238.             {
  1239.                 for (TypeSymbol *non_local_type = (TypeSymbol *) type -> non_local -> FirstElement();
  1240.                                  non_local_type;
  1241.                                  non_local_type = (TypeSymbol *) type -> non_local -> NextElement())
  1242.                 {
  1243.                     types -> Next() = non_local_type;
  1244.                 }
  1245.             }
  1246.  
  1247.             //
  1248.             // If we are supposed to generate code, do so now !!!
  1249.             //
  1250.             if (option.bytecode)
  1251.             {
  1252.                 for (int k = 0; k < types -> Length(); k++)
  1253.                 {
  1254.                     TypeSymbol *type = (*types)[k];
  1255.  
  1256.                     type -> file_symbol -> SetFileNameLiteral((Control *) this); // make sure the literal is available for bytecode
  1257.  
  1258.                     ByteCode *code = new ByteCode(type);
  1259.                     code -> GenerateCode();
  1260.  
  1261.                     delete code;
  1262.                 }
  1263.             }
  1264.  
  1265.             //
  1266.             // If no error was detected while generating code, then
  1267.             // start cleaning up.
  1268.             //
  1269.             if (! option.nocleanup)
  1270.             {
  1271.             if (sem -> NumErrors() == 0)
  1272.             {
  1273.                 for (int k = 0; k < types -> Length(); k++)
  1274.                 {
  1275.                     TypeSymbol *type = (*types)[k];
  1276.  
  1277.                     delete type -> semantic_environment;
  1278.                     type -> semantic_environment = NULL;
  1279.  
  1280.                     if (type -> ACC_INTERFACE())
  1281.                     {
  1282.                         AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration;
  1283.                         interface_declaration -> semantic_environment = NULL;
  1284.                     }
  1285.                     else
  1286.                     {
  1287.                         AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
  1288.  
  1289.                         if (class_declaration)
  1290.                             class_declaration -> semantic_environment = NULL;
  1291.                     }
  1292.                 }
  1293.             }
  1294.  
  1295.             delete types;
  1296.         }
  1297.     }
  1298.     }
  1299.  
  1300.     sem -> types_to_be_processed.RemoveElement(type);
  1301.     if (! option.nocleanup)
  1302.     if (sem -> types_to_be_processed.Size() == 0) // all types belonging to this compilation unit have been processed.
  1303.         CleanUp(sem -> source_file_symbol);
  1304.  
  1305.     return;
  1306. }
  1307.  
  1308.  
  1309. //
  1310. // Introduce the main package and the current package.
  1311. // This procedure is invoked directly only while doing
  1312. // an incremental compilation.
  1313. //
  1314. void Control::ProcessPackageDeclaration(FileSymbol *file_symbol, AstPackageDeclaration *package_declaration)
  1315. {
  1316.     file_symbol -> package = (package_declaration
  1317.                                      ? FindOrInsertPackage(file_symbol -> lex_stream, package_declaration -> name)
  1318.                                      : unnamed_package);
  1319.  
  1320.     for (int i = 0; i < file_symbol -> lex_stream -> NumTypes(); i++)
  1321.     {
  1322.         LexStream::TokenIndex identifier_token = file_symbol -> lex_stream -> Next(file_symbol -> lex_stream -> Type(i));
  1323.         if (file_symbol -> lex_stream -> Kind(identifier_token) == TK_Identifier)
  1324.         {
  1325.             NameSymbol *name_symbol = file_symbol -> lex_stream -> NameSymbol(identifier_token);
  1326.             if (! file_symbol -> package -> FindTypeSymbol(name_symbol))
  1327.             {
  1328.                 TypeSymbol *type = file_symbol -> package -> InsertOuterTypeSymbol(name_symbol);
  1329.                 type -> file_symbol = file_symbol;
  1330.                 type -> outermost_type = type;
  1331.                 type -> supertypes_closure = new SymbolSet;
  1332.                 type -> subtypes = new SymbolSet;
  1333.                 type -> SetOwner(file_symbol -> package);
  1334.                 type -> SetSignature(*this);
  1335.                 type -> MarkSourcePending();
  1336.  
  1337.                 //
  1338.                 // If this type is contained in the unnamed package add it to the set
  1339.                 // unnamed_package_types if a type of similar name was not already there.
  1340.                 //
  1341.                 if ((! package_declaration) && (unnamed_package_types.Image(type -> Identity()) == NULL))
  1342.                     unnamed_package_types.AddElement(type);
  1343.             }
  1344.         }
  1345.     }
  1346.  
  1347.     return;
  1348. }
  1349.  
  1350.  
  1351. void Control::CleanUp(FileSymbol *file_symbol)
  1352. {
  1353.     Semantic *sem = file_symbol -> semantic;
  1354.  
  1355.     if (sem)
  1356.     {
  1357. #ifdef TEST
  1358.         if (option.debug_dump_lex)
  1359.         {
  1360.             sem -> lex_stream -> Reset(); // rewind input and ...
  1361.             sem -> lex_stream -> Dump();  // dump it!
  1362.         }
  1363.         if (option.debug_dump_ast)
  1364.             sem -> compilation_unit -> Print(*sem -> lex_stream);
  1365.         if (option.debug_unparse_ast)
  1366.         {
  1367.             if (option.debug_unparse_ast_debug)
  1368.               {
  1369.                 // which of these is correct?
  1370.                 sem -> compilation_unit -> debug_unparse = true;
  1371.                 Ast::debug_unparse = true;
  1372.               }
  1373.             sem -> compilation_unit -> Unparse(*sem -> lex_stream,
  1374.                                                "unparsed/");
  1375.         }
  1376. #endif
  1377.         sem -> PrintMessages();
  1378.         if (sem -> return_code > 0)
  1379.             return_code = 1;
  1380.  
  1381.         file_symbol -> CleanUp();
  1382.     }
  1383.  
  1384.     return;
  1385. }
  1386.